# @Time : 2024-10-19 10:39
# @Author : Fioman 
# @Phone : 13149920693
"""
集合: 无序,元素唯一,元素不可变
无序: 没有顺序,没有索引
元素唯一: 元素唯一性,可以用来去重
元素不可变: (整数,字符串,元组) 原因是底层通过哈希表,所以元素必须是可哈希的,就是不可变的
"""
# region 1. 创建集合
st = set()
print(f"type(st) = {type(st)}")
st = {}  # 注意空集合不能这么创建,因为这样创建的是字典
print(f"type(st) = {type(st)}")
# st = {"1", 2, "3", [1, 2, 3]} # 错误
# st = {"1", 2, (2, 3, 4), (1, 2, [1, 2, 3])} 即使这样也不行
st = {"1", 2, (2, 3, 4)}
print(f"type(st) = {type(st)}")
print(f"len(st) = {len(st)}")  # 获取长度
# endregion

# region 2. 访问集合元素
# 集合元素是无序的,不能通过索引来访问,只能通过in来判断是否存在于集合中
st = {"1", 2, (2, 3, 4)}
print(f"{'1' in st}")
print(f"{3 in st}")  # 3不在集合中(2,3,4)才是在集合中
# endregion

# region 3. 集合中添加元素 add()
st = {"1", 2, (2, 3, 4)}
st.add("2")
print(f"st = {st}")
# st.add({"2", "3"}) # 报错,集合中不能再添加集合
st.add((1, 2, 3))  # 但是可以添加元组
print(f"st = {st}")
# endregion

# region 4. 从集合中移除元素 remove | discard | pop
st = {"1", 2, (2, 3, 4), "2", 3, 4, 5, 6, 4, 5}
print(f"st : {st}")
# remove(item) 从集合中移除指定元素,如果不存在会报错
itemDel = 100
if itemDel in st:
    st.remove(itemDel)
else:
    print("要移除的项不存在")

# discard(item) 从集合中删除元素,如果元素不存在不会报错
itemDel = 100
st.discard(itemDel)

# pop() 从集合中随机的移除一个元素,并返回被移除的元素
item = st.pop()
print(f"item = {item}, after pop = {st}")
item = st.pop()
print(f"item = {item}, after pop = {st}")

# clear() 清空集合中的所有的元素
st.clear()
print(f"after clear = {st}")

# 删除一个集合
st = {"1", 2, (2, 3, 4)}
del st
# print(f"st : {st}") 删除之后就不能再次访问

# endregion

# region 5. 其他序列转换为集合去重,注意这个序列必须是可哈希的
# 不是所有的列表都可以转换为集合,下面这个就不行
# lst = [1, 2, 3, 4, 5, [1, 2, 3]]
lst = [1, 2, 3, "4", "5", (1, 2, 3), 1, 2, 3, "4", "5"]
st = set(lst)
print(f"st = {st}")
# endregion

# region 6. 集合合并 union (|)   update
# 1) union() 合并两个集合,就是求并集.结果返回,不改变操作项
st01 = {1, 2, 3}
st02 = {2, 3, 4}
unionSt = st01.union(st02)
print(f"unionSt = {unionSt},st01 = {st01},st02 = {st02}")
# 2) | 操作符 和union()一样
unionSt = st01 | st02
print(f"unionSt = {unionSt},st01 = {st01},st02 = {st02}")

# 3) a.update(b) 将b集合合并到a集合中,改变操作项
res = st01.update(st02)
print(f"res = {res},st01 = {st01},st02 = {st02}")
# endregion

# region 7. 查找交集 a.intersection(b) or &
st01 = {1, 2, 3, 4, 5}
st02 = {2, 3, 7, 8, 9}
interSt = st01.intersection(st02)
print(f"interSt = {interSt},st01 = {st01},st02 = {st02}")
interSt = st01 & st02
print(f"interSt = {interSt},st01 = {st01},st02 = {st02}")
interSt = st01 & set()  # 如果没有共同部分返回空集
print(f"interSt = {interSt},st01 = {st01},st02 = {st02}")
# endregion

# region 8. 差集 a.difference(b) 或 a - b
# a.difference(b) a - b  a和b的差集,就是只存在于a中但是不存在于b中的元素
stA = {1, 2, 3, 4}
stB = {3, 4, 5, 6}
difStAB = stA - stB
difStBa = stB.difference(stA)
print(f"difStAB: {difStAB},difStBa = {difStBa}")
# endregion

# region 9. 对称差集 a.symmetric_difference 或 a^b
# 什么是对称差集,就是去除掉它们的共同部分. a - b | b - a
stA = {1, 2, 3, 4}
stB = {3, 4, 5, 6}
symDifAB = stA.symmetric_difference(stB)
symDifBa = stB ^ stA
print(f"symDifAB: {symDifAB},symDifBa = {symDifBa}")  # 这两个是相同的
# endregion

# region 10. 子集和超集  issubset() | issuperset()
# 如果集合A的元素,在集合B中都能找到,则A是B的子集,B是A的超集
st1 = {1, 2, 3, 4}
st2 = {1, 2, 3, 4, 5, 6}
st3 = {1, 2, 3, 5, 6, 7}
print("st1 是 st2 的子集吗? ", st1.issubset(st2))
print("st3 是 st1 的超集吗?", st3.issuperset(st1))
print("空集合是任意集合的子集吗? ", set().issubset(st1))  # 空集合是任意集合的子集
# endregion

# region 11. 集合推导式 {expression for item in iterable}
squares = {x ** 2 for x in range(1, 6)}
print(f"squares = {squares}")
squares = {x ** 2 for x in range(10) if x % 2 == 0}
print(f"squares = {squares}")
# 嵌套循环的结合推导式,注意这里会创建9项
pairsVal = {(name, age) for name in ["Fioman", "Yueyue", "Hammer"] for age in [10, 12, 13]}
print(f"pairsVal = {pairsVal}")
# 如果你只是想要获取一项呢,就是名字和年龄对应
names = ["Fioman", "Yueyue", "Hammer"]
age = [10, 12, 13]
pairsVal = {(names[i], age[i]) for i in range(len(names))}
print(f"pairsVal = {pairsVal}")
# if else 条件筛选
result = {x ** 2 if x % 2 == 0 else x ** 3 for x in range(20)}
print(f"result = {result}")
# 处理复杂数据结构,比如从二维列表中,去重
nestedList = [[1, 2, 3], [2, 3, 4], [4, 5, 6]]
# uniqueElements = set(nestedList) # 不行,因为里面有列表,列表是不可以hash的
uniqueElements = {item for subList in nestedList for item in subList}
print(f"uniqueElements = {uniqueElements}")

# 集合推导式和字典结合使用.
dt = {"a": 1, "b": 2, "c": 3, "d": 2}
keysSet = {key for key in dt}
print(f"keysSet = {keysSet}")
valueSet = {value for value in dt.values()}
print(f"valueSet = {valueSet}")

# 不可变集合,集合中的元素不能添加和删除
frozenSet = frozenset({x for x in range(1, 6)})
print(f"frozenSet = {frozenSet}")
# frozenSet.add(1)
# frozenSet.pop()
del frozenSet  # 只能删除整个变量
# endregion

# region 12. 练习
itCompanies = {"FaceBook", "Google", "Microsoft", "Apple", "IBM", "Oracle", "Amazon"}
print(f"len(itCompanies) = {len(itCompanies)}")
itCompanies.add("Twitter")
print(f"itCompanies = {itCompanies}")
itCompanies.update({"Fioman", "Hengding"})
print(f"itCompanies = {itCompanies}")
popItem = itCompanies.pop()
print(f"popItem = {popItem}")
itCompanies.discard("Hengding")
print(f"itCompanies = {itCompanies}")
# 移除是移除掉某个元素,如果元素不存在会报错,而discard不会报错,他们都是返回None
# 而pop() 才是返回要移除掉的元素
A = {19, 22, 24, 20, 25, 26}
B = {19, 22, 20, 25, 26, 24, 28, 27}
unionSt = A.union(B)
print(f"unionSt = {unionSt},A = {A},B = {B}")
unionSt = A | B
print(f"unionSt = {unionSt},A = {A},B = {B}")
intersectionSt = A.intersection(B)
print(f"intersectionSt = {intersectionSt},A = {A},B = {B}")
intersectionSt = A & B
print(f"intersectionSt = {intersectionSt},A = {A},B = {B}")
print(f"A 是 B 的子集吗? ", A.issubset(B))
print(f"A & B = 空吗?", len(A & B) == 0)
print(f"A | B = ", A | B)
print(f"A ^ B = ", A ^ B)
print(f"A ^ B = ", A.symmetric_difference(B))
del A
del B
age = [22, 19, 24, 25, 26, 24, 25, 24]
ageSet = set(age)
print(len(age) > len(ageSet))
# endregion
